package LunaServer.config;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.HashMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;

/**
 * 配置管理器，用于从配置文件中加载和管理服务器配置
 */
public class ConfigManager {
    private JsonObject config;
    private static final String CONFIG_FILE = "server-config.json";
    private Gson gson = new GsonBuilder().setPrettyPrinting().create();

    public ConfigManager() {
        loadConfig();
    }

    /**
     * 加载配置文件
     */
    private void loadConfig() {
        try {
            if (Files.exists(Paths.get(CONFIG_FILE))) {
                String content = new String(Files.readAllBytes(Paths.get(CONFIG_FILE)), StandardCharsets.UTF_8);
                config = gson.fromJson(content, JsonObject.class);
            } else {
                System.out.println("配置文件 " + CONFIG_FILE + " 不存在，将使用默认配置");
                createDefaultConfig();
            }
        } catch (IOException | JsonSyntaxException ex) {
            System.out.println("加载配置文件时出错: " + ex.getMessage());
            createDefaultConfig();
        }

        // 确保config不为null
        if (config == null) {
            config = new JsonObject();
        }
    }

    /**
     * 创建默认配置文件
     */
    private void createDefaultConfig() {
        config = new JsonObject();
        
        // 添加服务器配置部分
        JsonObject server = new JsonObject();
        server.addProperty("port", 6003);
        config.add("server", server);
        
        // 添加数据库配置部分
        JsonObject database = new JsonObject();
        database.addProperty("url", "jdbc:postgresql://127.0.0.1:12345/postgres");
        database.addProperty("user", "postgres");
        database.addProperty("password", "lunamoon");
        config.add("database", database);

        // 添加路由配置部分
        JsonObject routes = new JsonObject();
        config.add("routes", routes);

        // 添加默认的路由编译依赖（以列表形式）
        JsonObject routeDependencies = new JsonObject();
        com.google.gson.JsonArray defaultClasspath = new com.google.gson.JsonArray();
        defaultClasspath.add("src");
        defaultClasspath.add("src/LunaServer/core");
        defaultClasspath.add("src/LunaServer/config");
        defaultClasspath.add("src/LunaServer/logging");
        defaultClasspath.add("src/LunaServer/routing");
        defaultClasspath.add("src/LunaServer/database");
        defaultClasspath.add("src/LunaServer/email");
        defaultClasspath.add("src/LunaServer/gui");
        defaultClasspath.add("src/LunaServer/user");
        defaultClasspath.add("src/LunaServer/util");
        defaultClasspath.add("lib/gson-gson-parent-2.13.2/gson/target/classes");
        defaultClasspath.add("lib/*");
        defaultClasspath.add("lib/javax.mail.jar");
        routeDependencies.add("classpath", defaultClasspath);
        config.add("routeDependencies", routeDependencies);

        saveConfig();
    }

    // -------------------------- 基本配置 --------------------------------
    /**
     * 获取字符串类型的配置值，支持点号分隔的嵌套属性访问
     * 例如: "database.url" 会查找 {"database": {"url": "value"}}
     * 
     * @param key          配置键，支持点号分隔的嵌套属性
     * @param defaultValue 默认值
     * @return 配置值
     */
    public String getProperty(String key, String defaultValue) {
        // 先尝试直接查找键（为了向后兼容）
        if (config.has(key)) {
            return config.get(key).getAsString();
        }
        
        // 如果直接没找到，尝试按点号分割进行嵌套查找
        String[] parts = key.split("\\.");
        JsonObject current = config;
        
        // 遍历到倒数第二个部分
        for (int i = 0; i < parts.length - 1; i++) {
            if (current.has(parts[i]) && current.get(parts[i]).isJsonObject()) {
                current = current.getAsJsonObject(parts[i]);
            } else {
                // 路径中某一级不存在或不是对象，返回默认值
                return defaultValue;
            }
        }
        
        // 查找最后一级
        String lastPart = parts[parts.length - 1];
        if (current.has(lastPart)) {
            return current.get(lastPart).getAsString();
        }
        
        return defaultValue;
    }

    /**
     * 重载：在对特定json对象内获取属性
     * 
     * @param object       目标对象
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 配置值
     */
    public String getProperty(JsonObject object, String key, String defaultValue) {
        if (object.has(key)) {
            return object.get(key).getAsString();
        }
        return defaultValue;
    }

    /**
     * 获取整数类型的配置值，支持点号分隔的嵌套属性访问
     * 
     * @param key          配置键，支持点号分隔的嵌套属性
     * @param defaultValue 默认值
     * @return 配置值
     */
    public int getIntProperty(String key, int defaultValue) {
        // 先尝试直接查找键（为了向后兼容）
        if (config.has(key)) {
            return config.get(key).getAsInt();
        }
        
        // 如果直接没找到，尝试按点号分割进行嵌套查找
        String[] parts = key.split("\\.");
        JsonObject current = config;
        
        // 遍历到倒数第二个部分
        for (int i = 0; i < parts.length - 1; i++) {
            if (current.has(parts[i]) && current.get(parts[i]).isJsonObject()) {
                current = current.getAsJsonObject(parts[i]);
            } else {
                // 路径中某一级不存在或不是对象，返回默认值
                return defaultValue;
            }
        }
        
        // 查找最后一级
        String lastPart = parts[parts.length - 1];
        if (current.has(lastPart)) {
            return current.get(lastPart).getAsInt();
        }
        
        return defaultValue;
    }

    /**
     * 重载：在对特定json对象内获取属性
     * 
     * @param object       目标对象
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 配置值
     */
    public int getIntProperty(JsonObject object, String key, int defaultValue) {
        if (object.has(key)) {
            return object.get(key).getAsInt();
        }
        return defaultValue;
    }

    /**
     * 获取64位浮点类型的配置值（我这里不打算提供32位浮点数），支持点号分隔的嵌套属性访问
     * 
     * @param key          配置键，支持点号分隔的嵌套属性
     * @param defaultValue 默认值
     * @return 配置值
     */
    public double getDoubleProperty(String key, double defaultValue) {
        // 先尝试直接查找键（为了向后兼容）
        if (config.has(key)) {
            return config.get(key).getAsDouble();
        }
        
        // 如果直接没找到，尝试按点号分割进行嵌套查找
        String[] parts = key.split("\\.");
        JsonObject current = config;
        
        // 遍历到倒数第二个部分
        for (int i = 0; i < parts.length - 1; i++) {
            if (current.has(parts[i]) && current.get(parts[i]).isJsonObject()) {
                current = current.getAsJsonObject(parts[i]);
            } else {
                // 路径中某一级不存在或不是对象，返回默认值
                return defaultValue;
            }
        }
        
        // 查找最后一级
        String lastPart = parts[parts.length - 1];
        if (current.has(lastPart)) {
            return current.get(lastPart).getAsDouble();
        }
        
        return defaultValue;
    }

    /**
     * 重载：在对特定json对象内获取属性
     * 
     * @param object       目标对象
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 配置值
     */
    public double getDoubleProperty(JsonObject object, String key, double defaultValue) {
        if (object.has(key)) {
            return object.get(key).getAsDouble();
        }
        return defaultValue;
    }

    /**
     * 设置配置值并保存到文件（字符串）
     * 
     * @param key   配置键
     * @param value 配置值
     */
    public void setProperty(String key, String value) {
        config.addProperty(key, value);
        saveConfig();
    }

    /**
     * 设置配置值并保存到文件（整数）
     * 
     * @param key   配置键
     * @param value 配置值
     */
    public void setProperty(String key, int value) {
        config.addProperty(key, value);
        saveConfig();
    }

    // --------------------------- 路由配置 -----------------------------------
    /**
     * 获取路由依赖配置（列表形式）
     * 
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 配置值列表
     */
    public java.util.List<String> getRouteDependencyList(String key, java.util.List<String> defaultValue) {
        if (config.has("routeDependencies")) {
            JsonObject routeDependencies = config.getAsJsonObject("routeDependencies");
            if (routeDependencies.has(key) && routeDependencies.get(key).isJsonArray()) {
                com.google.gson.JsonArray array = routeDependencies.getAsJsonArray(key);
                java.util.List<String> result = new java.util.ArrayList<>();
                for (int i = 0; i < array.size(); i++) {
                    result.add(array.get(i).getAsString());
                }
                return result;
            }
        }
        return defaultValue;
    }

    /**
     * 设置路由依赖配置（列表形式）
     * 
     * @param key   配置键
     * @param value 配置值列表
     */
    public void setRouteDependencyList(String key, java.util.List<String> value) {
        JsonObject routeDependencies;
        if (config.has("routeDependencies")) {
            routeDependencies = config.getAsJsonObject("routeDependencies");
        } else {
            routeDependencies = new JsonObject();
            config.add("routeDependencies", routeDependencies);
        }

        com.google.gson.JsonArray array = new com.google.gson.JsonArray();
        for (String item : value) {
            array.add(item);
        }
        routeDependencies.add(key, array);
        saveConfig();
    }

    /**
     * 获取路由依赖配置（字符串形式，向后兼容）
     * 
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 配置值
     */
    public String getRouteDependency(String key, String defaultValue) {
        java.util.List<String> list = getRouteDependencyList(key, null);
        if (list != null) {
            return String.join(";", list);
        }
        return defaultValue;
    }

    /**
     * 设置路由依赖配置（字符串形式，向后兼容）
     * 
     * @param key   配置键
     * @param value 配置值
     */
    public void setRouteDependency(String key, String value) {
        String[] items = value.split(";");
        java.util.List<String> list = new java.util.ArrayList<>();
        for (String item : items) {
            list.add(item.trim());
        }
        setRouteDependencyList(key, list);
    }

    /**
     * 添加路由配置
     * 
     * @param path     路由路径
     * @param filePath 路由处理文件路径
     */
    public void addRoute(String path, String filePath) {
        JsonObject routes;
        if (config.has("routes")) {
            routes = config.getAsJsonObject("routes");
        } else {
            routes = new JsonObject();
            config.add("routes", routes);
        }
        routes.addProperty(path, filePath);
        saveConfig();
    }

    /**
     * 移除路由配置
     * 
     * @param path 路由路径
     */
    public void removeRoute(String path) {
        if (config.has("routes")) {
            JsonObject routes = config.getAsJsonObject("routes");
            routes.remove(path);
            saveConfig();
        }
    }

    /**
     * 获取所有路由配置
     * 
     * @return 路由映射
     */
    public Map<String, String> getRoutes() {
        Map<String, String> routeMap = new HashMap<>();
        if (config != null && config.has("routes")) {
            try {
                JsonObject routes = config.getAsJsonObject("routes");
                for (String path : routes.keySet()) {
                    routeMap.put(path, routes.get(path).getAsString());
                }
            } catch (Exception e) {
                System.err.println("解析路由配置时出错: " + e.getMessage());
            }
        }
        return routeMap;
    }

    /**
     * 获取所有服务器配置
     * 
     * @return 路由映射
     */
    public Map<String, String> getServerConfigs() {
        Map<String, String> serverConfigMap = new HashMap<>();
        if (config != null && config.has("server")) {
            try {
                JsonObject serverConfig = config.getAsJsonObject("server");
                for (String path : serverConfig.keySet()) {
                    serverConfigMap.put(path, serverConfig.get(path).getAsString());
                }
            } catch (Exception e) {
                System.err.println("解析服务器配置时出错: " + e.getMessage());
            }
        }
        return serverConfigMap;
    }

    /**
     * 获取特定服务器配置
     */

    public String getServerProperty(String key, String defaultValue) {
        JsonObject serverConfig;
        if (config != null && config.has("server")) {
            try {
                serverConfig = config.getAsJsonObject("server");
                String result = getProperty(serverConfig, key, defaultValue);
                return result;
            } catch (Exception e) {
                System.err.println("解析服务器配置时出错: " + e.getMessage());
            }
        }
        return defaultValue;
    }

    /**
     * 保存配置到文件
     */
    private void saveConfig() {
        try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(CONFIG_FILE),
                StandardCharsets.UTF_8)) {
            gson.toJson(config, writer);
            System.out.println("配置已保存到: " + CONFIG_FILE);
        } catch (IOException io) {
            System.out.println("保存配置文件时出错: " + io.getMessage());
        }
    }
}